﻿Imports Microsoft.Win32
Imports System
Imports System.Collections
Imports System.Collections.Generic
Imports System.Diagnostics
Imports System.Globalization
Imports System.IO
Imports System.Reflection
Imports System.Reflection.Emit
Imports System.Runtime.CompilerServices
Imports System.Runtime.InteropServices
Imports System.Runtime.Remoting
Imports System.Runtime.Remoting.Channels
Imports System.Runtime.Remoting.Channels.Ipc
Imports System.Security.AccessControl
Imports System.Security.Permissions
Imports System.Security.Principal
Imports System.Threading
Imports System.Workflow.ComponentModel
Imports System.Workflow.ComponentModel.Compiler
Imports System.Workflow.ComponentModel.Design
Imports System.Workflow.ComponentModel.Serialization
Imports System.Workflow.Runtime
Imports System.Xml

Namespace System.Workflow.Runtime.DebugEngine
    Public NotInheritable Class DebugController
        Inherits MarshalByRefObject
        ' Methods
        Friend Sub New(ByVal serviceContainer As WorkflowRuntime, ByVal hostName As String)
            If (serviceContainer Is Nothing) Then
                Throw New ArgumentNullException("serviceContainer")
            End If
            Try 
                Me.programPublisher = New ProgramPublisher
            Catch obj1 As Object
                Return
            End Try
            Me.serviceContainer = serviceContainer
            Me.programId = Guid.Empty
            Me.controllerConduit = Nothing
            Me.channel = Nothing
            Me.isZombie = False
            Me.hostName = hostName
            AddHandler AppDomain.CurrentDomain.ProcessExit, New EventHandler(AddressOf Me.OnDomainUnload)
            AddHandler AppDomain.CurrentDomain.DomainUnload, New EventHandler(AddressOf Me.OnDomainUnload)
            AddHandler Me.serviceContainer.Started, New EventHandler([Of] WorkflowRuntimeEventArgs)(AddressOf Me.Start)
            AddHandler Me.serviceContainer.Stopped, New EventHandler([Of] WorkflowRuntimeEventArgs)(AddressOf Me.Stop)
        End Sub

        Friend Sub Attach(ByVal programId As Guid, ByVal attachTimeout As Integer, ByVal detachPingInterval As Integer, <Out> ByRef hostName As String, <Out> ByRef uri As String, <Out> ByRef controllerThreadId As Integer, <Out> ByRef isSynchronousAttach As Boolean)
            SyncLock Me.syncRoot
                hostName = String.Empty
                uri = String.Empty
                controllerThreadId = 0
                isSynchronousAttach = False
                If Not Me.isZombie Then
                    If Me.isAttached Then
                        Me.Detach
                    End If
                    Me.isAttached = True
                    Me.programId = programId
                    Me.debugControllerThread = New DebugControllerThread
                    Me.instanceTable = New InstanceTable(Me.debugControllerThread.ManagedThreadId)
                    Me.typeToGuid = New Dictionary([Of] Type, Guid)
                    Me.xomlHashToGuid = New Dictionary([Of] Byte(), Guid)(New DigestComparer)
                    Me.debugControllerThread.RunThread(Me.instanceTable)
                    Dim properties As IDictionary = New Hashtable
                    properties.Item("typeFilterLevel") = "Full"
                    Dim serverSinkProvider As New BinaryServerFormatterSinkProvider(properties, Nothing)
                    Dim hashtable As New Hashtable
                    hashtable.Item("name") = String.Empty
                    hashtable.Item("portName") = Me.programId.ToString
                    Dim reference As IdentityReference = New SecurityIdentifier(WellKnownSidType.BuiltinAdministratorsSid, Nothing).Translate(GetType(NTAccount))
                    hashtable.Item("authorizedGroup") = reference.ToString
                    Me.channel = New IpcChannel(hashtable, Nothing, serverSinkProvider)
                    ChannelServices.RegisterChannel(Me.channel, True)
                    RemotingServices.Marshal(Me, Me.programId.ToString)
                    hostName = Me.hostName
                    uri = Me.channel.GetUrlsForUri(Me.programId.ToString)(0)
                    controllerThreadId = Me.debugControllerThread.ThreadId
                    isSynchronousAttach = Not Me.isServiceContainerStarting
                    Me.attachTimeout = attachTimeout
                    Me.attachTimer = New Timer(New TimerCallback(AddressOf Me.AttachTimerCallback), Nothing, attachTimeout, detachPingInterval)
                End If
            End SyncLock
        End Sub

        Private Sub AttachTimerCallback(ByVal state As Object)
            Try 
                SyncLock Me.syncRoot
                    If ((Not Me.isZombie AndAlso Me.isAttached) AndAlso Not Debugger.IsAttached) Then
                        Me.attachTimer.Change(-1, -1)
                        Me.Detach
                    End If
                End SyncLock
            Catch obj1 As Object
            End Try
        End Sub

        Public Sub AttachToConduit(ByVal url As Uri)
            If (url Is Nothing) Then
                Throw New ArgumentNullException("url")
            End If
            Try 
                [Using] New DebuggerThreadMarker
                    Try 
                        Dim key As RegistryKey = Registry.LocalMachine.OpenSubKey(RegistryKeys.DebuggerSubKey)
                        If (Not key Is Nothing) Then
                            Dim str As String = [TryCast](key.GetValue(DebugController.ControllerConduitTypeName, String.Empty),String)
                            If (Not String.IsNullOrEmpty(str) AndAlso (Not Type.GetType(str) Is Nothing)) Then
                                Me.controllerConduit = [TryCast](Activator.GetObject(Type.GetType(str), url.AbsolutePath),IWorkflowDebugger)
                            End If
                        End If
                    Catch obj1 As Object
                    Finally
                        If (Me.controllerConduit Is Nothing) Then
                            Me.controllerConduit = [TryCast](Activator.GetObject(Type.GetType("Microsoft.Workflow.DebugEngine.ControllerConduit, Microsoft.Workflow.DebugController, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"), url.AbsolutePath),IWorkflowDebugger)
                        End If
                    End Try
                    If (Not Me.controllerConduit Is Nothing) Then
                        Me.eventLock = New Object
                        AddHandler AppDomain.CurrentDomain.AssemblyLoad, New AssemblyLoadEventHandler(AddressOf Me.OnAssemblyLoad)
                        Dim assembly As Assembly
                        For Each assembly In AppDomain.CurrentDomain.GetAssemblies
                            If (Not TypeOf [assembly] Is AssemblyBuilder AndAlso ([assembly].Location <> String.Empty)) Then
                                Me.controllerConduit.AssemblyLoaded(Me.programId, [assembly].Location, [assembly].GlobalAssemblyCache)
                            End If
                        Next
                        AddHandler Me.serviceContainer.DefinitionDispenser.WorkflowDefinitionLoaded, New EventHandler([Of] WorkflowDefinitionEventArgs)(AddressOf Me.ScheduleTypeLoaded)
                        Dim type As Type
                        For Each type In Me.serviceContainer.DefinitionDispenser.GetWorkflowTypes
                            Dim workflowDefinition As Activity = Me.serviceContainer.DefinitionDispenser.GetWorkflowDefinition(type)
                            Me.LoadExistingScheduleType(Me.GetScheduleTypeId(type), type, False, workflowDefinition)
                        Next
                        Dim buffer As Byte()
                        For Each buffer In Me.serviceContainer.DefinitionDispenser.GetWorkflowDefinitions
                            Dim rootActivity As Activity = Me.serviceContainer.DefinitionDispenser.GetWorkflowDefinition(buffer)
                            Dim activity3 As Activity = DirectCast(rootActivity.GetValue(Activity.WorkflowDefinitionProperty), Activity)
                            Dim list As ArrayList = Nothing
                            If (Not activity3 Is Nothing) Then
                                list = DirectCast(activity3.GetValue(WorkflowChanges.WorkflowChangeActionsProperty), ArrayList)
                            End If
                            Me.LoadExistingScheduleType(Me.GetScheduleTypeId(buffer), rootActivity.GetType, ((Not list Is Nothing) AndAlso (list.Count <> 0)), rootActivity)
                        Next
                        AddHandler Me.serviceContainer.WorkflowExecutorInitializing, New EventHandler([Of] WorkflowExecutorInitializingEventArgs)(AddressOf Me.InstanceInitializing)
                        Dim instance As WorkflowInstance
                        For Each instance In Me.serviceContainer.GetLoadedWorkflows
                            [Using] instance.GetWorkflowResourceUNSAFE.ExecutorLock.Enter
                                Me.LoadExistingInstance(instance, True)
                                [Continue] For
                            End [Using]
                        Next
                        Me.eventConduitAttached.Set
                    End If
                End [Using]
            Catch exception1 As Exception
            End Try
        End Sub

        Friend Sub Close()
            RemoveHandler AppDomain.CurrentDomain.ProcessExit, New EventHandler(AddressOf Me.OnDomainUnload)
            RemoveHandler AppDomain.CurrentDomain.DomainUnload, New EventHandler(AddressOf Me.OnDomainUnload)
            If Not Me.isZombie Then
                Me.Stop(Nothing, New WorkflowRuntimeEventArgs(False))
            End If
        End Sub

        Private Sub Detach()
            [Using] New DebuggerThreadMarker
                SyncLock Me.syncRoot
                    RemoveHandler AppDomain.CurrentDomain.AssemblyLoad, New AssemblyLoadEventHandler(AddressOf Me.OnAssemblyLoad)
                    If (Not Me.isZombie AndAlso Me.isAttached) Then
                        Me.isAttached = False
                        Me.programId = Guid.Empty
                        If (Not Me.debugControllerThread Is Nothing) Then
                            Me.debugControllerThread.StopThread
                            Me.debugControllerThread = Nothing
                        End If
                        If (Not Me.attachTimer Is Nothing) Then
                            Me.attachTimer.Change(-1, -1)
                            Me.attachTimer = Nothing
                        End If
                        RemotingServices.Disconnect(Me)
                        If (Not Me.channel Is Nothing) Then
                            ChannelServices.UnregisterChannel(Me.channel)
                            Me.channel = Nothing
                        End If
                        Me.controllerConduit = Nothing
                        Me.eventConduitAttached.Reset
                        Me.instanceTable = Nothing
                        Me.typeToGuid = Nothing
                        Me.xomlHashToGuid = Nothing
                        If Not Me.serviceContainer.IsZombie Then
                            Dim instance As WorkflowInstance
                            For Each instance In Me.serviceContainer.GetLoadedWorkflows
                                Dim workflowResourceUNSAFE As WorkflowExecutor = instance.GetWorkflowResourceUNSAFE
                                [Using] workflowResourceUNSAFE.ExecutorLock.Enter
                                    If workflowResourceUNSAFE.IsInstanceValid Then
                                        RemoveHandler workflowResourceUNSAFE.WorkflowExecutionEvent, New EventHandler([Of] WorkflowExecutionEventArgs)(AddressOf Me.OnInstanceEvent)
                                    End If
                                    [Continue] For
                                End [Using]
                            Next
                            RemoveHandler Me.serviceContainer.WorkflowExecutorInitializing, New EventHandler([Of] WorkflowExecutorInitializingEventArgs)(AddressOf Me.InstanceInitializing)
                            RemoveHandler Me.serviceContainer.DefinitionDispenser.WorkflowDefinitionLoaded, New EventHandler([Of] WorkflowDefinitionEventArgs)(AddressOf Me.ScheduleTypeLoaded)
                        End If
                    End If
                End SyncLock
            End [Using]
        End Sub

        Private Sub EnumerateEventHandlersForActivity(ByVal scheduleTypeId As Guid, ByVal activity As Activity)
            Dim handlerMethods As New List([Of] ActivityHandlerDescriptor)
            Dim method As MethodInfo = activity.GetType.GetMethod("System.Workflow.ComponentModel.IDependencyObjectAccessor.GetInvocationList", (BindingFlags.FlattenHierarchy Or (BindingFlags.NonPublic Or (BindingFlags.Public Or BindingFlags.Instance))))
            Dim info2 As EventInfo
            For Each info2 In activity.GetType.GetEvents((BindingFlags.FlattenHierarchy Or (BindingFlags.NonPublic Or (BindingFlags.Public Or BindingFlags.Instance))))
                Dim property As DependencyProperty = DependencyProperty.FromName(info2.Name, activity.GetType)
                If (Not [property] Is Nothing) Then
                    Try 
                        Dim delegate2 As Delegate
                        For Each delegate2 In [TryCast](method.MakeGenericMethod(New Type() { [property].PropertyType }).Invoke(activity, New Object() { [property] }),Delegate())
                            Dim descriptor As ActivityHandlerDescriptor
                            Dim info4 As MethodInfo = delegate2.Method
                            descriptor.Name = (info4.DeclaringType.FullName & "." & info4.Name)
                            descriptor.Token = info4.MetadataToken
                            handlerMethods.Add(descriptor)
                        Next
                    Catch obj1 As Object
                    End Try
                End If
            Next
            Me.controllerConduit.UpdateHandlerMethodsForActivity(Me.programId, scheduleTypeId, activity.QualifiedName, handlerMethods)
        End Sub

        Private Function GetContextId(ByVal activity As Activity) As Integer
            Return ContextActivityUtils.ContextId(ContextActivityUtils.ContextActivity(activity))
        End Function

        Private Function GetHierarchicalId(ByVal activity As Activity) As String
            Dim str As String = String.Empty
            Do While (Not activity Is Nothing)
                Dim str2 As String = String.Empty
                Dim activity2 As Activity = ContextActivityUtils.ContextActivity(activity)
                Dim num As Integer = ContextActivityUtils.ContextId(activity2)
                str2 = (activity.Name & If(((num > 1) AndAlso (activity Is activity2)), ("(" & num & ")"), String.Empty))
                str = If((str.Length > 0), (str2 & "." & str), str2)
                activity = activity.Parent
            Loop
            Return str
        End Function

        Private Function GetScheduleTypeId(ByVal scheduleType As Type) As Guid
            SyncLock Me.typeToGuid
                If Not Me.typeToGuid.ContainsKey(scheduleType) Then
                    Me.typeToGuid.Item(scheduleType) = Guid.NewGuid
                End If
                Return Me.typeToGuid.Item(scheduleType)
            End SyncLock
        End Function

        Private Function GetScheduleTypeId(ByVal workflowCoreRuntime As IWorkflowCoreRuntime) As Guid
            Dim rootActivity As Activity = workflowCoreRuntime.RootActivity
            If workflowCoreRuntime.IsDynamicallyUpdated Then
                Return workflowCoreRuntime.InstanceID
            End If
            If String.IsNullOrEmpty([TryCast](rootActivity.GetValue(Activity.WorkflowXamlMarkupProperty),String)) Then
                Return Me.GetScheduleTypeId(rootActivity.GetType)
            End If
            Return Me.GetScheduleTypeId([TryCast](rootActivity.GetValue(WorkflowDefinitionDispenser.WorkflowDefinitionHashCodeProperty),Byte()))
        End Function

        Private Function GetScheduleTypeId(ByVal scheduleDefHashCode As Byte()) As Guid
            SyncLock Me.xomlHashToGuid
                If Not Me.xomlHashToGuid.ContainsKey(scheduleDefHashCode) Then
                    Me.xomlHashToGuid.Item(scheduleDefHashCode) = Guid.NewGuid
                End If
                Return Me.xomlHashToGuid.Item(scheduleDefHashCode)
            End SyncLock
        End Function

        <SecurityPermission(SecurityAction.LinkDemand, Flags:=SecurityPermissionFlag.Infrastructure)> _
        Public Overrides Function InitializeLifetimeService() As Object
            Return Nothing
        End Function

        Friend Shared Sub InitializeProcessSecurity()
            Dim workerThreadException As Exception = Nothing
            Dim security As New ProcessSecurity
            Dim thread As New Thread(New ThreadStart(AddressOf security.Initialize))
            security.exceptionNotification = DirectCast(Delegate.Combine(security.exceptionNotification, Function (ByVal e As Exception) 
                workerThreadException = e
            End Function), ExceptionNotification)
            thread.Start
            thread.Join
            If (Not workerThreadException Is Nothing) Then
                Throw workerThreadException
            End If
        End Sub

        Private Sub InstanceCompleted(ByVal sender As Object, ByVal args As WorkflowEventArgs)
            Try 
                Me.UnloadExistingInstance(args.WorkflowInstance)
            Catch obj1 As Object
            End Try
        End Sub

        Private Sub InstanceInitializing(ByVal sender As Object, ByVal e As WorkflowExecutorInitializingEventArgs)
            Try 
                If e.Loading Then
                    Me.LoadExistingInstance(DirectCast(sender, WorkflowExecutor).WorkflowInstance, True)
                Else
                    Me.LoadExistingInstance(DirectCast(sender, WorkflowExecutor).WorkflowInstance, False)
                End If
            Catch obj1 As Object
            End Try
        End Sub

        Private Sub InstanceTerminated(ByVal sender As Object, ByVal args As WorkflowEventArgs)
            Try 
                Me.UnloadExistingInstance(args.WorkflowInstance)
            Catch obj1 As Object
            End Try
        End Sub

        Private Sub InstanceUnloaded(ByVal sender As Object, ByVal args As WorkflowEventArgs)
            Try 
                Me.UnloadExistingInstance(args.WorkflowInstance)
            Catch obj1 As Object
            End Try
        End Sub

        Private Sub LoadExistingInstance(ByVal instance As WorkflowInstance, ByVal attaching As Boolean)
            Dim workflowResourceUNSAFE As WorkflowExecutor = instance.GetWorkflowResourceUNSAFE
            If workflowResourceUNSAFE.IsInstanceValid Then
                Dim workflowCoreRuntime As IWorkflowCoreRuntime = workflowResourceUNSAFE
                Dim rootActivity As Activity = workflowCoreRuntime.RootActivity
                Dim scheduleTypeId As Guid = Me.GetScheduleTypeId(workflowCoreRuntime)
                If (attaching AndAlso workflowCoreRuntime.IsDynamicallyUpdated) Then
                    Me.LoadExistingScheduleType(scheduleTypeId, rootActivity.GetType, True, rootActivity)
                End If
                Me.instanceTable.AddInstance(instance.InstanceId, rootActivity)
                Me.controllerConduit.InstanceCreated(Me.programId, instance.InstanceId, scheduleTypeId)
                SyncLock Me.eventLock
                    AddHandler workflowResourceUNSAFE.WorkflowExecutionEvent, New EventHandler([Of] WorkflowExecutionEventArgs)(AddressOf Me.OnInstanceEvent)
                    Dim activity2 As Activity
                    For Each activity2 In DebugController.WalkActivityTree(rootActivity)
                        Me.UpdateActivityStatus(scheduleTypeId, instance.InstanceId, activity2)
                    Next
                    Dim rootContext As New ActivityExecutionContext(rootActivity)
                    Dim context2 As ActivityExecutionContext
                    For Each context2 In DebugController.WalkExecutionContextTree(rootContext)
                        Dim activity4 As Activity
                        For Each activity4 In DebugController.WalkActivityTree(context2.Activity)
                            Me.UpdateActivityStatus(scheduleTypeId, instance.InstanceId, activity4)
                        Next
                    Next
                End SyncLock
            End If
        End Sub

        Private Sub LoadExistingScheduleType(ByVal scheduleTypeId As Guid, ByVal scheduleType As Type, ByVal isDynamic As Boolean, ByVal rootActivity As Activity)
            If (rootActivity Is Nothing) Then
                Throw New InvalidOperationException
            End If
            [Using] writer As StringWriter = New StringWriter(CultureInfo.InvariantCulture)
                [Using] writer2 As XmlWriter = Helpers.CreateXmlWriter(writer)
                    New WorkflowMarkupSerializer().Serialize(writer2, rootActivity)
                    Dim fileName As String = Nothing
                    Dim str2 As String = Nothing
                    Dim customAttributes As Attribute() = [TryCast](scheduleType.GetCustomAttributes(GetType(WorkflowMarkupSourceAttribute), False),Attribute())
                    If ((Not customAttributes Is Nothing) AndAlso (customAttributes.Length = 1)) Then
                        fileName = DirectCast(customAttributes(0), WorkflowMarkupSourceAttribute).FileName
                        str2 = DirectCast(customAttributes(0), WorkflowMarkupSourceAttribute).MD5Digest
                    End If
                    Me.controllerConduit.ScheduleTypeLoaded(Me.programId, scheduleTypeId, scheduleType.Assembly.FullName, fileName, str2, isDynamic, scheduleType.FullName, scheduleType.Name, writer.ToString)
                End [Using]
            End [Using]
        End Sub

        Private Sub OnActivityExecuting(ByVal sender As Object, ByVal eventArgs As ActivityExecutingEventArgs)
            If (Not Me.isZombie AndAlso Me.isAttached) Then
                Try 
                    SyncLock Me.eventLock
                        Dim workflowCoreRuntime As IWorkflowCoreRuntime = DirectCast(sender, IWorkflowCoreRuntime)
                        Dim scheduleTypeId As Guid = Me.GetScheduleTypeId(workflowCoreRuntime)
                        Me.EnumerateEventHandlersForActivity(scheduleTypeId, eventArgs.Activity)
                        Me.controllerConduit.BeforeActivityStatusChanged(Me.programId, scheduleTypeId, workflowCoreRuntime.InstanceID, eventArgs.Activity.QualifiedName, Me.GetHierarchicalId(eventArgs.Activity), eventArgs.Activity.ExecutionStatus, Me.GetContextId(eventArgs.Activity))
                        Me.controllerConduit.ActivityStatusChanged(Me.programId, scheduleTypeId, workflowCoreRuntime.InstanceID, eventArgs.Activity.QualifiedName, Me.GetHierarchicalId(eventArgs.Activity), eventArgs.Activity.ExecutionStatus, Me.GetContextId(eventArgs.Activity))
                    End SyncLock
                Catch obj1 As Object
                End Try
            End If
        End Sub

        Private Sub OnActivityStatusChanged(ByVal sender As Object, ByVal eventArgs As ActivityStatusChangeEventArgs)
            If (Not Me.isZombie AndAlso Me.isAttached) Then
                Try 
                    SyncLock Me.eventLock
                        If (eventArgs.Activity.ExecutionStatus <> ActivityExecutionStatus.Executing) Then
                            Dim workflowCoreRuntime As IWorkflowCoreRuntime = DirectCast(sender, IWorkflowCoreRuntime)
                            Dim scheduleTypeId As Guid = Me.GetScheduleTypeId(workflowCoreRuntime)
                            If (eventArgs.Activity.ExecutionStatus = ActivityExecutionStatus.Executing) Then
                                Me.EnumerateEventHandlersForActivity(scheduleTypeId, eventArgs.Activity)
                            End If
                            Me.controllerConduit.BeforeActivityStatusChanged(Me.programId, scheduleTypeId, workflowCoreRuntime.InstanceID, eventArgs.Activity.QualifiedName, Me.GetHierarchicalId(eventArgs.Activity), eventArgs.Activity.ExecutionStatus, Me.GetContextId(eventArgs.Activity))
                            Me.controllerConduit.ActivityStatusChanged(Me.programId, scheduleTypeId, workflowCoreRuntime.InstanceID, eventArgs.Activity.QualifiedName, Me.GetHierarchicalId(eventArgs.Activity), eventArgs.Activity.ExecutionStatus, Me.GetContextId(eventArgs.Activity))
                        End If
                    End SyncLock
                Catch obj1 As Object
                End Try
            End If
        End Sub

        Private Sub OnAssemblyLoad(ByVal sender As Object, ByVal args As AssemblyLoadEventArgs)
            If (args.LoadedAssembly.Location <> String.Empty) Then
                Try 
                    Me.controllerConduit.AssemblyLoaded(Me.programId, args.LoadedAssembly.Location, args.LoadedAssembly.GlobalAssemblyCache)
                Catch obj1 As Object
                End Try
            End If
        End Sub

        Private Sub OnDomainUnload(ByVal sender As Object, ByVal e As EventArgs)
            Me.Stop(Nothing, Nothing)
        End Sub

        Private Sub OnHandlerInvoked(ByVal sender As Object, ByVal eventArgs As EventArgs)
            If (Not Me.isZombie AndAlso Me.isAttached) Then
                Try 
                    SyncLock Me.eventLock
                        Dim runtime As IWorkflowCoreRuntime = [TryCast](sender,IWorkflowCoreRuntime)
                        Me.controllerConduit.HandlerInvoked(Me.programId, runtime.InstanceID, NativeMethods.GetCurrentThreadId, Me.GetHierarchicalId(runtime.CurrentActivity))
                    End SyncLock
                Catch obj1 As Object
                End Try
            End If
        End Sub

        Private Sub OnHandlerInvoking(ByVal sender As Object, ByVal eventArgs As EventArgs)
        End Sub

        Private Sub OnInstanceEvent(ByVal sender As Object, ByVal e As WorkflowExecutionEventArgs)
            Dim eventType As WorkflowEventInternal = e.EventType
            If (eventType <= WorkflowEventInternal.Unloaded) Then
                If (eventType <> WorkflowEventInternal.Completed) Then
                    If (eventType = WorkflowEventInternal.Unloaded) Then
                        Me.InstanceUnloaded(sender, New WorkflowEventArgs(DirectCast(sender, WorkflowExecutor).WorkflowInstance))
                    End If
                    Return
                End If
            Else
                Select Case eventType
                    Case WorkflowEventInternal.Changed
                        Me.OnWorkflowChanged(sender, e)
                        Return
                    Case WorkflowEventInternal.HandlerInvoking
                        Me.OnHandlerInvoking(sender, e)
                        Return
                    Case WorkflowEventInternal.HandlerInvoked
                        Me.OnHandlerInvoked(sender, e)
                        Return
                    Case WorkflowEventInternal.ActivityExecuting
                        Me.OnActivityExecuting(sender, DirectCast(e, ActivityExecutingEventArgs))
                        Return
                    Case WorkflowEventInternal.ActivityStatusChange
                        Me.OnActivityStatusChanged(sender, DirectCast(e, ActivityStatusChangeEventArgs))
                        Return
                    Case WorkflowEventInternal.Terminated
                        Me.InstanceTerminated(sender, New WorkflowEventArgs(DirectCast(sender, WorkflowExecutor).WorkflowInstance))
                        Return
                End Select
                Return
            End If
            Me.InstanceCompleted(sender, New WorkflowEventArgs(DirectCast(sender, WorkflowExecutor).WorkflowInstance))
        End Sub

        Private Sub OnWorkflowChanged(ByVal sender As Object, ByVal eventArgs As EventArgs)
            If (Not Me.isZombie AndAlso Me.isAttached) Then
                Try 
                    SyncLock Me.eventLock
                        Dim runtime As IWorkflowCoreRuntime = DirectCast(sender, IWorkflowCoreRuntime)
                        Dim rootActivity As Activity = Me.instanceTable.GetRootActivity(runtime.InstanceID)
                        Dim instanceID As Guid = runtime.InstanceID
                        Me.LoadExistingScheduleType(instanceID, rootActivity.GetType, True, rootActivity)
                        Me.instanceTable.UpdateRootActivity(runtime.InstanceID, rootActivity)
                        Me.controllerConduit.InstanceDynamicallyUpdated(Me.programId, runtime.InstanceID, instanceID)
                    End SyncLock
                Catch obj1 As Object
                End Try
            End If
        End Sub

        Private Sub ScheduleTypeLoaded(ByVal sender As Object, ByVal args As WorkflowDefinitionEventArgs)
            Try 
                If (Not args.WorkflowType Is Nothing) Then
                    Dim workflowDefinition As Activity = DirectCast(sender, WorkflowRuntime).DefinitionDispenser.GetWorkflowDefinition(args.WorkflowType)
                    Me.LoadExistingScheduleType(Me.GetScheduleTypeId(args.WorkflowType), args.WorkflowType, False, workflowDefinition)
                Else
                    Dim rootActivity As Activity = DirectCast(sender, WorkflowRuntime).DefinitionDispenser.GetWorkflowDefinition(args.WorkflowDefinitionHashCode)
                    Me.LoadExistingScheduleType(Me.GetScheduleTypeId(args.WorkflowDefinitionHashCode), rootActivity.GetType, False, rootActivity)
                End If
            Catch obj1 As Object
            End Try
        End Sub

        Private Sub Start(ByVal source As Object, ByVal e As WorkflowRuntimeEventArgs)
            Me.isZombie = False
            Me.isAttached = False
            Me.eventConduitAttached = New ManualResetEvent(False)
            Me.isServiceContainerStarting = True
            Dim flag As Boolean = Me.programPublisher.Publish(Me)
            Do While ((flag AndAlso Me.isAttached) AndAlso Not Me.eventConduitAttached.WaitOne(Me.attachTimeout, False))
            Loop
            Me.isServiceContainerStarting = False
        End Sub

        Private Sub [Stop](ByVal source As Object, ByVal e As WorkflowRuntimeEventArgs)
            Try 
                SyncLock Me.syncRoot
                    Me.Detach
                    Me.programPublisher.Unpublish
                    Me.isZombie = True
                End SyncLock
            Catch obj1 As Object
            End Try
        End Sub

        Private Sub UnloadExistingInstance(ByVal instance As WorkflowInstance)
            Me.controllerConduit.InstanceCompleted(Me.programId, instance.InstanceId)
            Me.instanceTable.RemoveInstance(instance.InstanceId)
        End Sub

        Private Sub UpdateActivityStatus(ByVal scheduleTypeId As Guid, ByVal instanceId As Guid, ByVal activity As Activity)
            If (activity Is Nothing) Then
                Throw New ArgumentNullException("activity")
            End If
            If (activity.ExecutionStatus = ActivityExecutionStatus.Executing) Then
                Me.EnumerateEventHandlersForActivity(scheduleTypeId, activity)
            End If
            If (activity.ExecutionStatus <> ActivityExecutionStatus.Initialized) Then
                Dim stateReaderId As Integer = ContextActivityUtils.ContextId(ContextActivityUtils.ContextActivity(activity))
                Me.controllerConduit.SetInitialActivityStatus(Me.programId, scheduleTypeId, instanceId, activity.QualifiedName, Me.GetHierarchicalId(activity), activity.ExecutionStatus, stateReaderId)
            End If
        End Sub

        Private Shared Function WalkActivityTree(ByVal rootActivity As Activity) As IEnumerable
            Return New <WalkActivityTree>d__3(-2) { _
                .<>3__rootActivity = rootActivity _
            }
        End Function

        Private Shared Function WalkExecutionContextTree(ByVal rootContext As ActivityExecutionContext) As IEnumerable
            Return New <WalkExecutionContextTree>d__d(-2) { _
                .<>3__rootContext = rootContext _
            }
        End Function


        ' Fields
        Private attachTimeout As Integer
        Private attachTimer As Timer
        Private channel As IpcChannel
        Private controllerConduit As IWorkflowDebugger
        Private Shared ReadOnly ControllerConduitTypeName As String = "ControllerConduitTypeName"
        Private debugControllerThread As DebugControllerThread
        Private eventConduitAttached As ManualResetEvent
        Private eventLock As Object
        Private hostName As String
        Private instanceTable As InstanceTable
        Private isAttached As Boolean
        Private isServiceContainerStarting As Boolean
        Private isZombie As Boolean
        Private programId As Guid
        Private programPublisher As ProgramPublisher
        Private Const rootExecutorGuid As String = "98fcdc7a-8ab4-4fb7-92d4-20f437285729"
        Private serviceContainer As WorkflowRuntime
        Private syncRoot As Object = New Object
        Private typeToGuid As Dictionary(Of Type, Guid)
        Private xomlHashToGuid As Dictionary(Of Byte(), Guid)

        ' Nested Types
        <CompilerGenerated> _
        Private NotInheritable Class <WalkActivityTree>d__3
            Implements IEnumerable(Of Object), IEnumerable, IEnumerator(Of Object), IEnumerator, IDisposable
            ' Methods
            <DebuggerHidden> _
            Public Sub New(ByVal <>1__state As Integer)
                Me.<>1__state = <>1__state
                Me.<>l__initialThreadId = Thread.CurrentThread.ManagedThreadId
            End Sub

            Private Sub <>m__Finally7()
                Me.<>1__state = -1
                If (Not Me.<>7__wrap6 Is Nothing) Then
                    Me.<>7__wrap6.Dispose
                End If
            End Sub

            Private Sub <>m__Finallya()
                Me.<>1__state = 2
                Me.<>7__wrap9 = TryCast(Me.<>7__wrap8,IDisposable)
                If (Not Me.<>7__wrap9 Is Nothing) Then
                    Me.<>7__wrap9.Dispose
                End If
            End Sub

            Private Function MoveNext() As Boolean Implements IEnumerator.MoveNext
                Dim flag As Boolean
                Try 
                    Select Case Me.<>1__state
                        Case 0
                            Me.<>1__state = -1
                            If ((Me.rootActivity Is Nothing) OrElse Not Me.rootActivity.Enabled) Then
                                goto Label_012A
                            End If
                            Me.<>2__current = Me.rootActivity
                            Me.<>1__state = 1
                            Return True
                        Case 1
                            Me.<>1__state = -1
                            If Not TypeOf Me.rootActivity Is CompositeActivity Then
                                goto Label_012A
                            End If
                            Me.<>7__wrap6 = DirectCast(Me.rootActivity, CompositeActivity).Activities.GetEnumerator
                            Me.<>1__state = 2
                            goto Label_0114
                        Case 4
                            goto Label_00FA
                        Case Else
                            goto Label_012A
                    End Select
                Label_009D:
                    Me.<childActivity>5__4 = Me.<>7__wrap6.Current
                    Me.<>7__wrap8 = DebugController.WalkActivityTree(Me.<childActivity>5__4).GetEnumerator
                    Me.<>1__state = 3
                    Do While Me.<>7__wrap8.MoveNext
                        Me.<nestedChild>5__5 = DirectCast(Me.<>7__wrap8.Current, Activity)
                        Me.<>2__current = Me.<nestedChild>5__5
                        Me.<>1__state = 4
                        Return True
                    Label_00FA:
                        Me.<>1__state = 3
                    Loop
                    Me.<>m__Finallya
                Label_0114:
                    If Me.<>7__wrap6.MoveNext Then
                        goto Label_009D
                    End If
                    Me.<>m__Finally7
                Label_012A:
                    flag = False
                Fault
                    Me.System.IDisposable.Dispose
                End Try
                Return flag
            End Function

            <DebuggerHidden> _
            Private Function System.Collections.Generic.IEnumerable<System.Object>.GetEnumerator() As IEnumerator(Of Object) Implements IEnumerable(Of Object).GetEnumerator
                Dim d__ As <WalkActivityTree>d__3
                If ((Thread.CurrentThread.ManagedThreadId = Me.<>l__initialThreadId) AndAlso (Me.<>1__state = -2)) Then
                    Me.<>1__state = 0
                    d__ = Me
                Else
                    d__ = New <WalkActivityTree>d__3(0)
                End If
                d__.rootActivity = Me.<>3__rootActivity
                Return d__
            End Function

            <DebuggerHidden> _
            Private Function System.Collections.IEnumerable.GetEnumerator() As IEnumerator Implements IEnumerable.GetEnumerator
                Return Me.System.Collections.Generic.IEnumerable<System.Object>.GetEnumerator
            End Function

            <DebuggerHidden> _
            Private Sub System.Collections.IEnumerator.Reset() Implements IEnumerator.Reset
                Throw New NotSupportedException
            End Sub

            Private Sub System.IDisposable.Dispose() Implements IDisposable.Dispose
                Select Case Me.<>1__state
                    Case 2, 3, 4
                        Try 
                            Select Case Me.<>1__state
                                Case 3, 4
                                    Try 
                                    Finally
                                        Me.<>m__Finallya
                                    End Try
                                    Exit Select
                            End Select
                        Finally
                            Me.<>m__Finally7
                        End Try
                        Exit Select
                    Case Else
                        Return
                End Select
            End Sub


            ' Properties
            Private ReadOnly Property System.Collections.Generic.IEnumerator<System.Object>.Current As Object
                <DebuggerHidden> _
                Get
                    Return Me.<>2__current
                End Get
            End Property

            Private ReadOnly Property System.Collections.IEnumerator.Current As Object
                <DebuggerHidden> _
                Get
                    Return Me.<>2__current
                End Get
            End Property


            ' Fields
            Private <>1__state As Integer
            Private <>2__current As Object
            Public <>3__rootActivity As Activity
            Public <>7__wrap6 As IEnumerator(Of Activity)
            Public <>7__wrap8 As IEnumerator
            Public <>7__wrap9 As IDisposable
            Private <>l__initialThreadId As Integer
            Public <childActivity>5__4 As Activity
            Public <nestedChild>5__5 As Activity
            Public rootActivity As Activity
        End Class

        <CompilerGenerated> _
        Private NotInheritable Class <WalkExecutionContextTree>d__d
            Implements IEnumerable(Of Object), IEnumerable, IEnumerator(Of Object), IEnumerator, IDisposable
            ' Methods
            <DebuggerHidden> _
            Public Sub New(ByVal <>1__state As Integer)
                Me.<>1__state = <>1__state
                Me.<>l__initialThreadId = Thread.CurrentThread.ManagedThreadId
            End Sub

            Private Sub <>m__Finally11()
                Me.<>1__state = -1
                If (Not Me.<>7__wrap10 Is Nothing) Then
                    Me.<>7__wrap10.Dispose
                End If
            End Sub

            Private Sub <>m__Finally14()
                Me.<>1__state = 2
                Me.<>7__wrap13 = TryCast(Me.<>7__wrap12,IDisposable)
                If (Not Me.<>7__wrap13 Is Nothing) Then
                    Me.<>7__wrap13.Dispose
                End If
            End Sub

            Private Function MoveNext() As Boolean Implements IEnumerator.MoveNext
                Dim flag As Boolean
                Try 
                    Select Case Me.<>1__state
                        Case 0
                            Me.<>1__state = -1
                            If (Me.rootContext Is Nothing) Then
                                goto Label_010A
                            End If
                            Me.<>2__current = Me.rootContext
                            Me.<>1__state = 1
                            Return True
                        Case 1
                            Me.<>1__state = -1
                            Me.<>7__wrap10 = Me.rootContext.ExecutionContextManager.ExecutionContexts.GetEnumerator
                            Me.<>1__state = 2
                            goto Label_00F4
                        Case 4
                            goto Label_00DA
                        Case Else
                            goto Label_010A
                    End Select
                Label_007D:
                    Me.<executionContext>5__e = Me.<>7__wrap10.Current
                    Me.<>7__wrap12 = DebugController.WalkExecutionContextTree(Me.<executionContext>5__e).GetEnumerator
                    Me.<>1__state = 3
                    Do While Me.<>7__wrap12.MoveNext
                        Me.<nestedContext>5__f = DirectCast(Me.<>7__wrap12.Current, ActivityExecutionContext)
                        Me.<>2__current = Me.<nestedContext>5__f
                        Me.<>1__state = 4
                        Return True
                    Label_00DA:
                        Me.<>1__state = 3
                    Loop
                    Me.<>m__Finally14
                Label_00F4:
                    If Me.<>7__wrap10.MoveNext Then
                        goto Label_007D
                    End If
                    Me.<>m__Finally11
                Label_010A:
                    flag = False
                Fault
                    Me.System.IDisposable.Dispose
                End Try
                Return flag
            End Function

            <DebuggerHidden> _
            Private Function System.Collections.Generic.IEnumerable<System.Object>.GetEnumerator() As IEnumerator(Of Object) Implements IEnumerable(Of Object).GetEnumerator
                Dim _d As <WalkExecutionContextTree>d__d
                If ((Thread.CurrentThread.ManagedThreadId = Me.<>l__initialThreadId) AndAlso (Me.<>1__state = -2)) Then
                    Me.<>1__state = 0
                    _d = Me
                Else
                    _d = New <WalkExecutionContextTree>d__d(0)
                End If
                _d.rootContext = Me.<>3__rootContext
                Return _d
            End Function

            <DebuggerHidden> _
            Private Function System.Collections.IEnumerable.GetEnumerator() As IEnumerator Implements IEnumerable.GetEnumerator
                Return Me.System.Collections.Generic.IEnumerable<System.Object>.GetEnumerator
            End Function

            <DebuggerHidden> _
            Private Sub System.Collections.IEnumerator.Reset() Implements IEnumerator.Reset
                Throw New NotSupportedException
            End Sub

            Private Sub System.IDisposable.Dispose() Implements IDisposable.Dispose
                Select Case Me.<>1__state
                    Case 2, 3, 4
                        Try 
                            Select Case Me.<>1__state
                                Case 3, 4
                                    Try 
                                    Finally
                                        Me.<>m__Finally14
                                    End Try
                                    Exit Select
                            End Select
                        Finally
                            Me.<>m__Finally11
                        End Try
                        Exit Select
                    Case Else
                        Return
                End Select
            End Sub


            ' Properties
            Private ReadOnly Property System.Collections.Generic.IEnumerator<System.Object>.Current As Object
                <DebuggerHidden> _
                Get
                    Return Me.<>2__current
                End Get
            End Property

            Private ReadOnly Property System.Collections.IEnumerator.Current As Object
                <DebuggerHidden> _
                Get
                    Return Me.<>2__current
                End Get
            End Property


            ' Fields
            Private <>1__state As Integer
            Private <>2__current As Object
            Public <>3__rootContext As ActivityExecutionContext
            Public <>7__wrap10 As IEnumerator(Of ActivityExecutionContext)
            Public <>7__wrap12 As IEnumerator
            Public <>7__wrap13 As IDisposable
            Private <>l__initialThreadId As Integer
            Public <executionContext>5__e As ActivityExecutionContext
            Public <nestedContext>5__f As ActivityExecutionContext
            Public rootContext As ActivityExecutionContext
        End Class

        Private Delegate Sub ExceptionNotification(ByVal e As Exception)

        Private Class ProcessSecurity
            ' Methods
            Private Function FindIndexInDacl(ByVal newAce As CommonAce, ByVal dacl As RawAcl) As Integer
                Dim num As Integer = 0
                num = 0
                Do While (num < dacl.Count)
                    If ((TypeOf dacl.Item(num) Is CommonAce AndAlso (DirectCast(dacl.Item(num), CommonAce).SecurityIdentifier.Value = newAce.SecurityIdentifier.Value)) AndAlso (dacl.Item(num).AceType = newAce.AceType)) Then
                        Return -1
                    End If
                    If (((newAce.AceType <> AceType.AccessDenied) OrElse (dacl.Item(num).AceType <> AceType.AccessDenied)) OrElse (newAce.IsInherited OrElse dacl.Item(num).IsInherited)) Then
                        If ((newAce.AceType = AceType.AccessDenied) AndAlso Not newAce.IsInherited) Then
                            Return num
                        End If
                        If ((((newAce.AceType <> AceType.AccessAllowed) OrElse (dacl.Item(num).AceType <> AceType.AccessAllowed)) OrElse (newAce.IsInherited OrElse dacl.Item(num).IsInherited)) AndAlso ((newAce.AceType = AceType.AccessAllowed) AndAlso Not newAce.IsInherited)) Then
                            Return num
                        End If
                    End If
                    num += 1
                Loop
                Return num
            End Function

            Private Function GetCurrentProcessTokenDacl() As RawAcl
                Dim discretionaryAcl As RawAcl
                Dim zero As IntPtr = IntPtr.Zero
                Dim tokenHandle As IntPtr = IntPtr.Zero
                Dim pSecurityDescriptor As IntPtr = IntPtr.Zero
                Try 
                    Dim num As UInt32
                    zero = NativeMethods.GetCurrentProcess
                    If Not NativeMethods.OpenProcessToken(zero, &HF00FF, tokenHandle) Then
                        Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error)
                    End If
                    NativeMethods.GetKernelObjectSecurity(tokenHandle, SECURITY_INFORMATION.DACL_SECURITY_INFORMATION, IntPtr.Zero, 0, num)
                    Marshal.GetLastWin32Error
                    pSecurityDescriptor = Marshal.AllocCoTaskMem(CInt(num))
                    If Not NativeMethods.GetKernelObjectSecurity(tokenHandle, SECURITY_INFORMATION.DACL_SECURITY_INFORMATION, pSecurityDescriptor, num, num) Then
                        Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error)
                    End If
                    Dim destination As Byte() = New Byte(num  - 1) {}
                    Marshal.Copy(pSecurityDescriptor, destination, 0, CInt(num))
                    Dim descriptor As New RawSecurityDescriptor(destination, 0)
                    discretionaryAcl = descriptor.DiscretionaryAcl
                Finally
                    If (((zero <> IntPtr.Zero) AndAlso (zero <> DirectCast(-1, IntPtr))) AndAlso Not NativeMethods.CloseHandle(zero)) Then
                        Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error)
                    End If
                    If ((tokenHandle <> IntPtr.Zero) AndAlso Not NativeMethods.CloseHandle(tokenHandle)) Then
                        Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error)
                    End If
                    If (pSecurityDescriptor <> IntPtr.Zero) Then
                        Marshal.FreeCoTaskMem(pSecurityDescriptor)
                    End If
                End Try
                Return discretionaryAcl
            End Function

            Friend Sub Initialize()
                Try 
                    If Not NativeMethods.RevertToSelf Then
                        Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error)
                    End If
                    Dim currentProcessTokenDacl As RawAcl = Me.GetCurrentProcessTokenDacl
                    Dim newAce As New CommonAce(AceFlags.None, AceQualifier.AccessAllowed, 8, New SecurityIdentifier(WellKnownSidType.BuiltinAdministratorsSid, Nothing), False, Nothing)
                    Dim index As Integer = Me.FindIndexInDacl(newAce, currentProcessTokenDacl)
                    If (index <> -1) Then
                        currentProcessTokenDacl.InsertAce(index, newAce)
                    End If
                    Me.SetCurrentProcessTokenDacl(currentProcessTokenDacl)
                Catch exception As Exception
                    If (Not Me.exceptionNotification Is Nothing) Then
                        Me.exceptionNotification.Invoke(exception)
                    End If
                End Try
            End Sub

            Private Sub SetCurrentProcessTokenDacl(ByVal dacl As RawAcl)
                Dim zero As IntPtr = IntPtr.Zero
                Dim tokenHandle As IntPtr = IntPtr.Zero
                Dim pSecurityDescriptor As IntPtr = IntPtr.Zero
                Try 
                    Dim num As UInt32
                    zero = NativeMethods.GetCurrentProcess
                    If Not NativeMethods.OpenProcessToken(zero, &HF00FF, tokenHandle) Then
                        Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error)
                    End If
                    NativeMethods.GetKernelObjectSecurity(tokenHandle, SECURITY_INFORMATION.DACL_SECURITY_INFORMATION, IntPtr.Zero, 0, num)
                    Marshal.GetLastWin32Error
                    pSecurityDescriptor = Marshal.AllocCoTaskMem(CInt(num))
                    If Not NativeMethods.GetKernelObjectSecurity(tokenHandle, SECURITY_INFORMATION.DACL_SECURITY_INFORMATION, pSecurityDescriptor, num, num) Then
                        Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error)
                    End If
                    Dim destination As Byte() = New Byte(num  - 1) {}
                    Marshal.Copy(pSecurityDescriptor, destination, 0, CInt(num))
                    Dim descriptor As New RawSecurityDescriptor(destination, 0) { _
                        .DiscretionaryAcl = dacl _
                    }
                    destination = New Byte(descriptor.BinaryLength  - 1) {}
                    descriptor.GetBinaryForm(destination, 0)
                    Marshal.FreeCoTaskMem(pSecurityDescriptor)
                    pSecurityDescriptor = Marshal.AllocCoTaskMem(descriptor.BinaryLength)
                    Marshal.Copy(destination, 0, pSecurityDescriptor, descriptor.BinaryLength)
                    If Not NativeMethods.SetKernelObjectSecurity(tokenHandle, SECURITY_INFORMATION.DACL_SECURITY_INFORMATION, pSecurityDescriptor) Then
                        Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error)
                    End If
                Finally
                    If (((zero <> IntPtr.Zero) AndAlso (zero <> DirectCast(-1, IntPtr))) AndAlso Not NativeMethods.CloseHandle(zero)) Then
                        Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error)
                    End If
                    If ((tokenHandle <> IntPtr.Zero) AndAlso Not NativeMethods.CloseHandle(tokenHandle)) Then
                        Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error)
                    End If
                    If (pSecurityDescriptor <> IntPtr.Zero) Then
                        Marshal.FreeCoTaskMem(pSecurityDescriptor)
                    End If
                End Try
            End Sub


            ' Fields
            Friend exceptionNotification As ExceptionNotification
        End Class
    End Class
End Namespace

